﻿using System.Globalization;

namespace Microsoft.Xna.Framework.Graphics
{
	/// <summary>
	/// Defines input vertex data to the pipeline.
	/// </summary>
	public struct VertexElement
	{
		#region Fields
		internal int _offset;
		internal VertexElementFormat _format;
		internal VertexElementUsage _usage;
		internal int _usageIndex;
		#endregion

		#region Properties
		/// <summary>
		/// Retrieves or sets the offset (if any) from the beginning of the stream to the beginning of the vertex data.
		/// </summary>
		public int Offset
		{
			get { return _offset; }
			set { _offset = value; }
		}

		/// <summary>
		/// Modifies the usage data to allow the user to specify multiple usage types.
		/// </summary>
		public int UsageIndex
		{
			get { return _usageIndex; }
			set { _usageIndex = value; }
		}

		/// <summary>
		/// Gets or sets the format of this vertex element.
		/// </summary>
		public VertexElementFormat VertexElementFormat
		{
			get { return _format; }
			set { _format = value; }
		}

		/// <summary>
		/// Gets or sets a value describing how the vertex element is to be used.
		/// </summary>
		public VertexElementUsage VertexElementUsage
		{
			get { return _usage; }
			set { _usage = value; }
		}
		#endregion

		/// <summary>
		/// Initializes a new instance of the VertexElement class.
		/// </summary>
		/// <param name="offset">Offset (if any) from the beginning of the stream to the beginning of the vertex data.</param>
		/// <param name="elementFormat">One of several predefined types that define the vertex data size.</param>
		/// <param name="elementUsage">The intended use of the vertex data.</param>
		/// <param name="usageIndex">Modifies the usage data to allow the user to specify multiple usage types.</param>
		public VertexElement(int offset, VertexElementFormat elementFormat, VertexElementUsage elementUsage, int usageIndex)
		{
			this._format = elementFormat;
			this._offset = offset;
			this._usage = elementUsage;
			this._usageIndex = usageIndex;
		}

		#region Public Methods
		/// <summary>
		/// Returns a value that indicates whether the current instance is equal to a specified object.
		/// </summary>
		/// <param name="obj">The Object to compare with the current VertexElement.</param>
		public override bool Equals(object obj)
		{
			if (obj != null)
			{
				if (obj is VertexElement)
				{
					return this == (VertexElement)obj;
				}
			}
			return false;
		}

		/// <summary>
		/// Gets the hash code for this instance.
		/// </summary>
		public override int GetHashCode()
		{
			return _format.GetHashCode() + _offset.GetHashCode() + _usage.GetHashCode() + _usageIndex.GetHashCode();
		}

		/// <summary>
		/// Retrieves a string representation of this object.
		/// </summary>
		public override string ToString()
		{
			return string.Format(CultureInfo.CurrentCulture, "{{Offset:{0} Format:{1} Usage:{2} UsageIndex:{3}}}", this.Offset, this.VertexElementFormat, this.VertexElementUsage, this.UsageIndex);
		}
		#endregion

		#region Operators
		/// <summary>
		/// Compares two objects to determine whether they are the same.
		/// </summary>
		/// <param name="left">Object to the left of the equality operator.</param>
		/// <param name="right">Object to the right of the equality operator.</param>
		public static bool operator ==(VertexElement left, VertexElement right)
		{
			return ((left._format == right._format) && (left._offset == right._offset) &&
					(left._usage == right._usage) && (left._usageIndex == right._usageIndex));
		}

		/// <summary>
		/// Compares two objects to determine whether they are different.
		/// </summary>
		/// <param name="left">Object to the left of the inequality operator.</param>
		/// <param name="right">Object to the right of the inequality operator.</param>
		public static bool operator !=(VertexElement left, VertexElement right)
		{
			return ((left._format != right._format) || (left._offset != right._offset) ||
					(left._usage != right._usage) || (left._usageIndex != right._usageIndex));
		}
		#endregion
	}
}
